﻿/******************************************************************************
 * Name         : Client.cpp
 * Author       : 671643387
 * Date         : 2015年9月11日
 * Description  :
 *****************************************************************************/

#include "Common.h"
#include "Client.hpp"
using namespace dev;
using namespace dev::net;

extern std::string gsaddr;
extern int gsport;
extern int gsbufsize;
extern char* gscscMSG;

Client::Client(int id, dev::net::EventLoop& eventLoop)
: id_(id)
, sock_(AF_INET, SOCK_STREAM)
, firstSend(true)
, status_(READY)
, buffer_(new char[gsbufsize])
, eventLoop_(eventLoop)
{

}

Client::~Client()
{

}

bool Client::open()
{
    if (!sock_.isValid())
    {
        sock_.reset(net::SocketApi::socket(AF_INET, SOCK_STREAM));
        if (!sock_.isValid())
            return false;
    }

    sock_.setUserDataInt(id_);

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
#if defined(__WINDOWS__)
    addr.sin_addr.S_un.S_addr = ::inet_addr(gsaddr.c_str());
#elif defined(__LINUX__)
    addr.sin_addr.s_addr = ::inet_addr(gsaddr.c_str());
#endif
    addr.sin_port = ::htons(gsport);

    if (!net::SocketApi::connect(sock_.getSocket(), (const struct sockaddr*)&addr, sizeof(addr)))
        return false;

    eventLoop_.addSocket(&sock_, dev::net::Reactor::ALL, this);
    status_ = RUNNING;
    return true;
}
void Client::close()
{
    dec_conn();
    status_ = EXIT;
}

void Client::shutdown()
{
    eventLoop_.removeSocket(&sock_);
    status_ = EXITING;
}

void Client::doSend(const char* buff, size_t len)
{
    int ret = sock_.send(buff, len);
    if (ret == SOCKET_ERROR)
    {
        if (ret == dev::net::SOCKET_ERROR_WOULDBLOCK)
            return;
        shutdown();
    }
    else
    {
        add_transfered_bytes(ret);
        inc_packets();
    }   
}

///////////////////////////////////////////////////////////////////////////////

void Client::handleInput()
{
    if (status_ != RUNNING)
        return;

    int ret = sock_.receive(&buffer_[0], gsbufsize);
    if (ret == SOCKET_ERROR)
    {
        if (ret == dev::net::SOCKET_ERROR_WOULDBLOCK)
            return;
        shutdown();
    }
    else 
    {
        add_transfered_bytes(ret);
        inc_packets();
    }
}

void Client::handleOutput()
{
    if (status_ != RUNNING)
        return;

    if (!firstSend)
    {
        doSend(&buffer_[0], gsbufsize);
    }
    else
    {
        doSend(gscscMSG, gsbufsize);
    }
}

void Client::handleException()
{
    if (status_ != RUNNING)
        return;

    shutdown();
}

void Client::handleClose()
{

}

void Client::handleHeartBeat()
{

}